﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace MyDemo.Reflection
{
    /// <summary>
    /// Emit示例
    ///http://www.cnblogs.com/gaochundong/archive/2013/06/01/csharp_emit_generate_assembly.html
    /// </summary>
    public class EmitDemo
    {
        #region Emit动态生成代码
        /// <summary>
        /// Emit动态生成代码
        /// </summary>
        public void Test()
        {
            // specify a new assembly name
            var assemblyName = new AssemblyName("Kitty");
            // create assembly builder
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            // create module builder
            var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");
            // create type builder for a class
            var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);
            // create method builder
            var methodBuilder = typeBuilder.DefineMethod("SayHelloMethod", 
                MethodAttributes.Public | MethodAttributes.Static, null, null);
            // then get the method IL generator
            var il = methodBuilder.GetILGenerator();
            // then create the method function
            il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
            il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
            il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));
            il.Emit(OpCodes.Pop);  // we just read something here ,throw it.
            il.Emit(OpCodes.Ret);
            // then create the whole class type
            var helloKittyClassType = typeBuilder.CreateType();
            // set entry point for this assembly
            assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));
            // save assembly
            assemblyBuilder.Save("Kitty11.exe");
            //
            Console.WriteLine("Hi, Dennis, a Kitty assembly has been generated for you.");
            Console.ReadLine();
        }
        #endregion

        #region Emit动态生成代码
        /// <summary>
        /// Emit动态生成代码
        /// </summary>
        public void Test1()
        {

        }
        #endregion
    }
}
